/**
 ** @author:   浓咖啡
 ** @date:     2019.1.23
 ** @brief:    字节流处理模块
 */

#include <assert.h>
#include "byte_array.h"

/**
 * 判断字符是否A-F或者a-f
 * @param  ch [字符]
 * @return    [1:是 0：不是]
 */
int is_A2F(char ch)
{
    if (ch>='A' && ch<='F'){
        return 1;
    }else if(ch>='a' && ch<='f'){
        return 1;
    }else{
        return 0;
    }
}

/**
 * 字符串转16进制："560A"转成{0x56, 0x0a}
 * @param  dst [目标地址]
 * @param  src [原字符串]
 * @param  len [字符串长度]
 * @return     [失败返回-1，成功返回0]
 */
int ba_str2hex(unsigned char *dst, const char *src, int len)
{
    int i = 0;
    int j = 0;

    char h, l;

    while(i < len){
        if(is_A2F(src[i])){
            h = src[i] - 0x37;
        }else if(isdigit(src[i])){
            h = src[i] - '0';
        }else{
            return -1;
        }
        i++;
        if(is_A2F(src[i])){
            l = src[i] - 0x37;
        }else if(isdigit(src[i])){
            l = src[i] - '0';
        }else{
            return -1;
        }
        i++;

        //拼接
        dst[j] = (h<<4) | l;
        j++;
    }

    return 0;
}


//取整个buf数组的第n位
int BIT_ISSET(int n, unsigned const char *buf)
{
    //先计算读第几个字节
    int nbytes = n / 8;

    //再计算读这个字节的哪一位
    int nbits = n % 8;

    return ((buf[nbytes]&(1<<nbits)) == 0 ? 0 : 1);
}

//设置整个buf数组的第n位为1
void BIT_SET(int n, unsigned char *buf)
{
    //先计算设置第几个字节
    int nbytes = n / 8;

    //再计算写这个字节的哪一位
    int nbits = n % 8;

    buf[nbytes] |= (1 << nbits);
}

//设置整个buf数组的第n位为0
void BIT_ZERO(int n, unsigned char *buf)
{
    //先计算设置第几个字节
    int nbytes = n / 8;

    //再计算写这个字节的哪一位
    int nbits = n % 8;

    buf[nbytes] &= ~(1 << nbits);
}

/**
 * 从src流中截取若干位，并移位到dst中，无越界保护
 * @param  dst   [description]
 * @param  src   [description]
 * @param  start [从哪一位开始取]
 * @param  num   [取多少位]
 */
void get_bit(unsigned char *dst, const unsigned char *src, int start, int num)
{
    //printf("start = %d, num = %d\n", start, num);
    int i;
    int src_i = start;
    int dst_i = 0;  //目标肯定从0开始
    for(i=0; i<num; i++)
    {
        if(BIT_ISSET(src_i, src) != 0){
            BIT_SET(dst_i, dst);
        }else{
            BIT_ZERO(dst_i, dst);
        }

        src_i++;
        dst_i++;
    }
}

/**
 * @brief 校验计算
 * @param data
 * @param start
 * @param end
 * @return
 */
unsigned char calc_chesum(const unsigned char *data, int start, int end)
{
    int i;
    unsigned char sum = 0;

    assert(start >= 0 && end >= start);

    for(i=start; i<=end; i++){
        sum += data[i];
    }

    return (unsigned char)sum & 0xff;
}

